<template>
  <div class="bg-white tree">
    <BasicTree title="设备列表" treeWrapperClassName="h-[calc(100%-35px)] overflow-auto" :clickRowToExpand="false"
      :treeData="treeData" :checkable="true"
      :fieldNames="{ key: 'treeId', title: 'classifyName', children: 'children' }" :selectedKeys="selectedKeys"
      :checkedKeys="checkedKeys" @check="handleCheck" @select="handleSelect" :loading="loadingRef"
      :expandedKeys="expandedKeys" />
  </div>
</template>
<script lang="ts"
  setup>
  import { onMounted, PropType, ref } from 'vue';
  import { BasicTree, TreeItem } from '@/components/Tree';
  import { getClassifyTree } from '@/api/collection/classify';

  const props = defineProps({
    width: {
      type: String as PropType<string>,
      default: '50%',
    },
    height: {
      type: String as PropType<string>,
      default: 'calc(100vh - 50vh)',
    },
    treeParam: {

    },
    fetchFn: {
      type: Function,
      default: getClassifyTree
    },
    initCheck: {
      type: Boolean,
      default: true
    },
    isDisabled: Boolean
  });
  defineOptions({ name: 'DeptTree' });

  const emit = defineEmits(['select', 'click']);

  const treeData = ref<TreeItem[]>([]);

  let selectedKeys = ref([]);
  let checkedKeys = ref([]);
  let loadingRef = ref(false)
  let expandedKeys = ref([])

  async function fetch() {
    loadingRef.value = true
    const fn = props.fetchFn
    const data = (await fn(props.treeParam)) as unknown as TreeItem[];
    loadingRef.value = false
    const setData = props.isDisabled ? setDisabledTreeNode(data) : data
    treeData.value = setData
    if (props.initCheck) {
      getInitNode(setData)
    }
  }

  const findFirstCheckableNodeAndPath = (nodes: any[], path: any[] = [], count = 0) => {
    if (!Array.isArray(nodes) || nodes.length === 0) return null

    for (const node of nodes) {
      const currentPath = [...path, node] // 当前路径
      const select = props.isDisabled ? node.checkable : true
      if (select) {
        const checkedChildren = node.children ? findCheckedChildren(node.children, currentPath) : []
        return currentPath.concat(checkedChildren)
      }

      if (node.children) {
        const result = findFirstCheckableNodeAndPath(node.children, currentPath)
        if (result) return result
      }
    }

    return null
  }

  const findCheckedChildren = (nodes, path) => {
    let checkableNodes: any[] = []
    for (const node of nodes) {
      const currentPath = [...path, node] // 当前路径
      const select = props.isDisabled ? node.checkable : true
      if (select) {
        checkableNodes.push(node)
        if (node.children) {
          checkableNodes = checkableNodes.concat(findCheckedChildren(node.children, currentPath))
        }
      }
    }
    return checkableNodes
  }
  const getInitNode = (arr) => {
    // 这里返回的是包含父path 的全部节点
    const result = findFirstCheckableNodeAndPath(arr)
    const checkedNodes = props.isDisabled ? result.filter(item => item.checkable) : result
    const checkedKeys = checkedNodes.map(item => item.treeId)
    const keys = result.map(item => item.treeId)
    expandedKeys.value = keys
    handleCheck(checkedKeys, { checkedNodes })
  }

  const getRootNodeIds = (nodes) => {
    return nodes.map(node => {
      if (node.children && node.children.length) {
        return getRootNodeIds(node.children);
      }
      return node.id;
    }).flat();
  };

  // 设置节点值的函数

  const setDisabledTreeNode = (arr) => {
    const data = arr.map(item => {
      // 创建新对象，保留原有属性并设置check为false
      let newItem = { ...item, checkable: item.type === 1 };

      // 如果有children属性且是数组，递归调用
      if (newItem.children && Array.isArray(newItem.children)) {
        newItem.children = setDisabledTreeNode(newItem.children);
      }

      return newItem;
    })
    return data
  };

  function handleSelect(keys) {
    emit('select', keys[0]);
    selectedKeys = ref(keys);
  }

  function handleCheck(keys, a) {
    emit('click', keys, a.checkedNodes);
    checkedKeys = ref(keys)
  }

  onMounted(() => {
    fetch();
  });
</script>
<style scoped>
.tree {
  flex-shrink: 0;
  margin-right: 8px;
}
</style>
